package com.datagateway.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 降级管理器
 * 负责实现系统降级策略，包括功能降级、服务降级、数据降级等
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class DegradationManager {

    private static final Logger logger = LoggerFactory.getLogger(DegradationManager.class);

    @Autowired
    private AlertManager alertManager;

    /**
     * 降级统计
     */
    private final AtomicLong totalRequests = new AtomicLong(0);
    private final AtomicLong totalDegradedRequests = new AtomicLong(0);
    private final AtomicLong totalFallbackRequests = new AtomicLong(0);
    private final AtomicLong totalDegradationTriggers = new AtomicLong(0);

    /**
     * 降级配置
     */
    private boolean degradationEnabled = true;
    private double defaultCpuThreshold = 80.0;
    private double defaultMemoryThreshold = 85.0;
    private double defaultResponseTimeThreshold = 5000.0;
    private double defaultErrorRateThreshold = 10.0;
    private int defaultDegradationDuration = 300; // 5分钟

    /**
     * 降级策略存储
     */
    private final Map<String, DegradationStrategy> degradationStrategies = new ConcurrentHashMap<>();
    private final Map<String, DegradationConfig> degradationConfigs = new ConcurrentHashMap<>();
    private final Map<String, DegradationStatus> degradationStatuses = new ConcurrentHashMap<>();

    /**
     * 执行器
     */
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2, r -> {
        Thread t = new Thread(r, "degradation-manager");
        t.setDaemon(true);
        return t;
    });

    /**
     * 初始化降级管理器
     */
    public void initialize() {
        try {
            // 启动降级监控任务
            startDegradationMonitoringTask();
            
            logger.info("降级管理器初始化成功");
            
        } catch (Exception e) {
            logger.error("降级管理器初始化失败", e);
            alertManager.sendSystemErrorAlert("降级管理器初始化失败", e.getMessage());
        }
    }

    /**
     * 停止降级管理器
     */
    public void stop() {
        try {
            scheduler.shutdown();
            if (!scheduler.awaitTermination(30, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
            
            logger.info("降级管理器停止成功");
            
        } catch (Exception e) {
            logger.error("降级管理器停止失败", e);
        }
    }

    /**
     * 创建降级策略
     * 
     * @param key 降级键
     * @param strategyType 策略类型
     * @param threshold 阈值
     * @param duration 持续时间
     * @param fallbackAction 降级动作
     * @return 是否创建成功
     */
    public boolean createDegradationStrategy(String key, String strategyType, double threshold, 
                                           int duration, String fallbackAction) {
        if (!degradationEnabled) {
            logger.debug("降级已禁用，跳过降级策略创建: {}", key);
            return false;
        }

        try {
            DegradationStrategy strategy = new DegradationStrategy(
                key, strategyType, threshold, duration, fallbackAction
            );

            degradationStrategies.put(key, strategy);
            
            DegradationConfig config = new DegradationConfig(
                key, strategyType, threshold, duration, fallbackAction
            );
            degradationConfigs.put(key, config);
            
            DegradationStatus status = new DegradationStatus(
                key, DegradationState.NORMAL, 0, 0, 0, System.currentTimeMillis()
            );
            degradationStatuses.put(key, status);
            
            logger.info("降级策略创建成功: {} (类型: {}, 阈值: {}, 持续时间: {}s)", 
                       key, strategyType, threshold, duration);
            
            return true;
            
        } catch (Exception e) {
            logger.error("创建降级策略失败: {}", key, e);
            alertManager.sendSystemErrorAlert("创建降级策略失败", e.getMessage());
            return false;
        }
    }

    /**
     * 检查是否需要降级
     * 
     * @param key 降级键
     * @param currentValue 当前值
     * @return 是否需要降级
     */
    public boolean shouldDegrade(String key, double currentValue) {
        if (!degradationEnabled) {
            return false;
        }

        try {
            DegradationStrategy strategy = degradationStrategies.get(key);
            if (strategy == null) {
                return false;
            }

            DegradationStatus status = degradationStatuses.get(key);
            if (status == null) {
                return false;
            }

            // 检查是否超过阈值
            boolean shouldDegrade = currentValue > strategy.getThreshold();
            
            if (shouldDegrade && status.getState() == DegradationState.NORMAL) {
                // 触发降级
                triggerDegradation(key, currentValue);
            } else if (!shouldDegrade && status.getState() == DegradationState.DEGRADED) {
                // 检查是否可以恢复
                checkRecovery(key, currentValue);
            }
            
            return status.getState() == DegradationState.DEGRADED;
            
        } catch (Exception e) {
            logger.error("检查降级状态失败: {}", key, e);
            return false;
        }
    }

    /**
     * 执行降级请求
     * 
     * @param key 降级键
     * @param request 请求
     * @return 执行结果
     */
    public <T> DegradationResult<T> executeWithDegradation(String key, DegradationRequest<T> request) {
        try {
            totalRequests.incrementAndGet();
            
            DegradationStatus status = degradationStatuses.get(key);
            if (status != null && status.getState() == DegradationState.DEGRADED) {
                totalDegradedRequests.incrementAndGet();
                return executeFallback(key, request);
            }
            
            // 正常执行
            T result = request.execute();
            return new DegradationResult<>(result, false, "SUCCESS", null);
            
        } catch (Exception e) {
            logger.error("执行降级请求失败: {}", key, e);
            return new DegradationResult<>(null, true, "ERROR", e.getMessage());
        }
    }

    /**
     * 获取降级状态
     * 
     * @param key 降级键
     * @return 降级状态
     */
    public DegradationStatus getDegradationStatus(String key) {
        return degradationStatuses.get(key);
    }

    /**
     * 获取所有降级状态
     * 
     * @return 降级状态列表
     */
    public List<DegradationStatus> getAllDegradationStatus() {
        return new ArrayList<>(degradationStatuses.values());
    }

    /**
     * 手动触发降级
     * 
     * @param key 降级键
     * @param reason 降级原因
     * @return 是否触发成功
     */
    public boolean triggerDegradation(String key, String reason) {
        try {
            DegradationStatus status = degradationStatuses.get(key);
            if (status == null) {
                return false;
            }

            status.setState(DegradationState.DEGRADED);
            status.setLastTriggerTime(System.currentTimeMillis());
            status.setTriggerCount(status.getTriggerCount() + 1);
            totalDegradationTriggers.incrementAndGet();
            
            logger.warn("手动触发降级: {} (原因: {})", key, reason);
            alertManager.sendSystemErrorAlert("系统降级", "降级键: " + key + ", 原因: " + reason);
            
            return true;
            
        } catch (Exception e) {
            logger.error("手动触发降级失败: {}", key, e);
            return false;
        }
    }

    /**
     * 手动恢复降级
     * 
     * @param key 降级键
     * @return 是否恢复成功
     */
    public boolean recoverDegradation(String key) {
        try {
            DegradationStatus status = degradationStatuses.get(key);
            if (status == null) {
                return false;
            }

            status.setState(DegradationState.NORMAL);
            status.setLastRecoveryTime(System.currentTimeMillis());
            status.setRecoveryCount(status.getRecoveryCount() + 1);
            
            logger.info("手动恢复降级: {}", key);
            
            return true;
            
        } catch (Exception e) {
            logger.error("手动恢复降级失败: {}", key, e);
            return false;
        }
    }

    /**
     * 删除降级策略
     * 
     * @param key 降级键
     * @return 是否删除成功
     */
    public boolean removeDegradationStrategy(String key) {
        try {
            DegradationStrategy removed = degradationStrategies.remove(key);
            degradationConfigs.remove(key);
            degradationStatuses.remove(key);
            
            if (removed != null) {
                logger.info("降级策略删除成功: {}", key);
                return true;
            }
            
            return false;
            
        } catch (Exception e) {
            logger.error("删除降级策略失败: {}", key, e);
            return false;
        }
    }

    /**
     * 获取降级统计信息
     * 
     * @return 统计信息
     */
    public DegradationStatistics getStatistics() {
        return new DegradationStatistics(
            totalRequests.get(),
            totalDegradedRequests.get(),
            totalFallbackRequests.get(),
            totalDegradationTriggers.get(),
            degradationStrategies.size(),
            degradationConfigs.size(),
            degradationStatuses.size(),
            degradationEnabled,
            defaultCpuThreshold,
            defaultMemoryThreshold,
            defaultResponseTimeThreshold,
            defaultErrorRateThreshold,
            System.currentTimeMillis()
        );
    }

    /**
     * 设置降级配置
     * 
     * @param enabled 是否启用降级
     * @param cpuThreshold CPU阈值
     * @param memoryThreshold 内存阈值
     * @param responseTimeThreshold 响应时间阈值
     * @param errorRateThreshold 错误率阈值
     * @param degradationDuration 降级持续时间
     */
    public void setConfiguration(boolean enabled, double cpuThreshold, double memoryThreshold,
                               double responseTimeThreshold, double errorRateThreshold, int degradationDuration) {
        this.degradationEnabled = enabled;
        this.defaultCpuThreshold = cpuThreshold;
        this.defaultMemoryThreshold = memoryThreshold;
        this.defaultResponseTimeThreshold = responseTimeThreshold;
        this.defaultErrorRateThreshold = errorRateThreshold;
        this.defaultDegradationDuration = degradationDuration;
        
        logger.info("降级配置已更新: 启用={}, CPU阈值={}, 内存阈值={}, 响应时间阈值={}, 错误率阈值={}, 降级持续时间={}s", 
                   enabled, cpuThreshold, memoryThreshold, responseTimeThreshold, errorRateThreshold, degradationDuration);
    }

    /**
     * 触发降级
     */
    private void triggerDegradation(String key, double currentValue) {
        try {
            DegradationStatus status = degradationStatuses.get(key);
            if (status != null) {
                status.setState(DegradationState.DEGRADED);
                status.setLastTriggerTime(System.currentTimeMillis());
                status.setTriggerCount(status.getTriggerCount() + 1);
                totalDegradationTriggers.incrementAndGet();
                
                logger.warn("触发降级: {} (当前值: {}, 阈值: {})", 
                           key, currentValue, degradationStrategies.get(key).getThreshold());
                alertManager.sendSystemErrorAlert("系统降级", 
                    "降级键: " + key + ", 当前值: " + currentValue);
            }
        } catch (Exception e) {
            logger.error("触发降级失败: {}", key, e);
        }
    }

    /**
     * 检查恢复
     */
    private void checkRecovery(String key, double currentValue) {
        try {
            DegradationStatus status = degradationStatuses.get(key);
            if (status != null && status.getState() == DegradationState.DEGRADED) {
                long timeSinceTrigger = System.currentTimeMillis() - status.getLastTriggerTime();
                DegradationStrategy strategy = degradationStrategies.get(key);
                
                if (timeSinceTrigger > strategy.getDuration() * 1000) {
                    status.setState(DegradationState.NORMAL);
                    status.setLastRecoveryTime(System.currentTimeMillis());
                    status.setRecoveryCount(status.getRecoveryCount() + 1);
                    
                    logger.info("降级恢复: {} (当前值: {})", key, currentValue);
                }
            }
        } catch (Exception e) {
            logger.error("检查恢复失败: {}", key, e);
        }
    }

    /**
     * 执行降级动作
     */
    private <T> DegradationResult<T> executeFallback(String key, DegradationRequest<T> request) {
        try {
            totalFallbackRequests.incrementAndGet();
            
            DegradationStrategy strategy = degradationStrategies.get(key);
            if (strategy != null) {
                String fallbackAction = strategy.getFallbackAction();
                
                switch (fallbackAction.toUpperCase()) {
                    case "RETURN_DEFAULT":
                        return new DegradationResult<>(null, true, "FALLBACK_DEFAULT", "返回默认值");
                    case "RETURN_CACHED":
                        return new DegradationResult<>(null, true, "FALLBACK_CACHED", "返回缓存数据");
                    case "RETURN_ERROR":
                        return new DegradationResult<>(null, true, "FALLBACK_ERROR", "返回错误信息");
                    case "SKIP_PROCESSING":
                        return new DegradationResult<>(null, true, "FALLBACK_SKIP", "跳过处理");
                    default:
                        return new DegradationResult<>(null, true, "FALLBACK_UNKNOWN", "未知降级动作");
                }
            }
            
            return new DegradationResult<>(null, true, "FALLBACK_DEFAULT", "默认降级");
            
        } catch (Exception e) {
            logger.error("执行降级动作失败: {}", key, e);
            return new DegradationResult<>(null, true, "FALLBACK_ERROR", e.getMessage());
        }
    }

    /**
     * 启动降级监控任务
     */
    private void startDegradationMonitoringTask() {
        scheduler.scheduleAtFixedRate(this::monitorDegradation, 
            0, 30, TimeUnit.SECONDS);
    }

    /**
     * 监控降级
     */
    private void monitorDegradation() {
        try {
            // 检查降级状态和自动恢复
            for (DegradationStatus status : degradationStatuses.values()) {
                if (status.getState() == DegradationState.DEGRADED) {
                    long timeSinceTrigger = System.currentTimeMillis() - status.getLastTriggerTime();
                    DegradationStrategy strategy = degradationStrategies.get(status.getKey());
                    
                    if (strategy != null && timeSinceTrigger > strategy.getDuration() * 1000) {
                        status.setState(DegradationState.NORMAL);
                        status.setLastRecoveryTime(System.currentTimeMillis());
                        status.setRecoveryCount(status.getRecoveryCount() + 1);
                        
                        logger.info("自动恢复降级: {}", status.getKey());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("监控降级失败", e);
        }
    }

    /**
     * 降级策略类
     */
    public static class DegradationStrategy {
        private final String key;
        private final String strategyType;
        private final double threshold;
        private final int duration;
        private final String fallbackAction;

        public DegradationStrategy(String key, String strategyType, double threshold, 
                                int duration, String fallbackAction) {
            this.key = key;
            this.strategyType = strategyType;
            this.threshold = threshold;
            this.duration = duration;
            this.fallbackAction = fallbackAction;
        }

        // Getter方法
        public String getKey() { return key; }
        public String getStrategyType() { return strategyType; }
        public double getThreshold() { return threshold; }
        public int getDuration() { return duration; }
        public String getFallbackAction() { return fallbackAction; }
    }

    /**
     * 降级状态枚举
     */
    public enum DegradationState {
        NORMAL,   // 正常状态
        DEGRADED  // 降级状态
    }

    /**
     * 降级请求接口
     */
    @FunctionalInterface
    public interface DegradationRequest<T> {
        T execute() throws Exception;
    }

    /**
     * 降级结果类
     */
    public static class DegradationResult<T> {
        private final T result;
        private final boolean degraded;
        private final String status;
        private final String message;

        public DegradationResult(T result, boolean degraded, String status, String message) {
            this.result = result;
            this.degraded = degraded;
            this.status = status;
            this.message = message;
        }

        // Getter方法
        public T getResult() { return result; }
        public boolean isDegraded() { return degraded; }
        public String getStatus() { return status; }
        public String getMessage() { return message; }
    }

    /**
     * 降级状态类
     */
    public static class DegradationStatus {
        private final String key;
        private DegradationState state;
        private int triggerCount;
        private int recoveryCount;
        private long lastTriggerTime;
        private long lastRecoveryTime;
        private final long timestamp;

        public DegradationStatus(String key, DegradationState state, int triggerCount, 
                               int recoveryCount, long lastTriggerTime, long timestamp) {
            this.key = key;
            this.state = state;
            this.triggerCount = triggerCount;
            this.recoveryCount = recoveryCount;
            this.lastTriggerTime = lastTriggerTime;
            this.timestamp = timestamp;
        }

        // Getter和Setter方法
        public String getKey() { return key; }
        public DegradationState getState() { return state; }
        public void setState(DegradationState state) { this.state = state; }
        public int getTriggerCount() { return triggerCount; }
        public void setTriggerCount(int triggerCount) { this.triggerCount = triggerCount; }
        public int getRecoveryCount() { return recoveryCount; }
        public void setRecoveryCount(int recoveryCount) { this.recoveryCount = recoveryCount; }
        public long getLastTriggerTime() { return lastTriggerTime; }
        public void setLastTriggerTime(long lastTriggerTime) { this.lastTriggerTime = lastTriggerTime; }
        public long getLastRecoveryTime() { return lastRecoveryTime; }
        public void setLastRecoveryTime(long lastRecoveryTime) { this.lastRecoveryTime = lastRecoveryTime; }
        public long getTimestamp() { return timestamp; }
    }

    /**
     * 降级配置类
     */
    public static class DegradationConfig {
        private final String key;
        private final String strategyType;
        private final double threshold;
        private final int duration;
        private final String fallbackAction;

        public DegradationConfig(String key, String strategyType, double threshold, 
                               int duration, String fallbackAction) {
            this.key = key;
            this.strategyType = strategyType;
            this.threshold = threshold;
            this.duration = duration;
            this.fallbackAction = fallbackAction;
        }

        // Getter方法
        public String getKey() { return key; }
        public String getStrategyType() { return strategyType; }
        public double getThreshold() { return threshold; }
        public int getDuration() { return duration; }
        public String getFallbackAction() { return fallbackAction; }
    }

    /**
     * 降级统计信息类
     */
    public static class DegradationStatistics {
        private final long totalRequests;
        private final long totalDegradedRequests;
        private final long totalFallbackRequests;
        private final long totalDegradationTriggers;
        private final int activeStrategies;
        private final int totalConfigs;
        private final int totalStatuses;
        private final boolean degradationEnabled;
        private final double defaultCpuThreshold;
        private final double defaultMemoryThreshold;
        private final double defaultResponseTimeThreshold;
        private final double defaultErrorRateThreshold;
        private final long timestamp;

        public DegradationStatistics(long totalRequests, long totalDegradedRequests, long totalFallbackRequests,
                                   long totalDegradationTriggers, int activeStrategies, int totalConfigs, int totalStatuses,
                                   boolean degradationEnabled, double defaultCpuThreshold, double defaultMemoryThreshold,
                                   double defaultResponseTimeThreshold, double defaultErrorRateThreshold, long timestamp) {
            this.totalRequests = totalRequests;
            this.totalDegradedRequests = totalDegradedRequests;
            this.totalFallbackRequests = totalFallbackRequests;
            this.totalDegradationTriggers = totalDegradationTriggers;
            this.activeStrategies = activeStrategies;
            this.totalConfigs = totalConfigs;
            this.totalStatuses = totalStatuses;
            this.degradationEnabled = degradationEnabled;
            this.defaultCpuThreshold = defaultCpuThreshold;
            this.defaultMemoryThreshold = defaultMemoryThreshold;
            this.defaultResponseTimeThreshold = defaultResponseTimeThreshold;
            this.defaultErrorRateThreshold = defaultErrorRateThreshold;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getTotalRequests() { return totalRequests; }
        public long getTotalDegradedRequests() { return totalDegradedRequests; }
        public long getTotalFallbackRequests() { return totalFallbackRequests; }
        public long getTotalDegradationTriggers() { return totalDegradationTriggers; }
        public int getActiveStrategies() { return activeStrategies; }
        public int getTotalConfigs() { return totalConfigs; }
        public int getTotalStatuses() { return totalStatuses; }
        public boolean isDegradationEnabled() { return degradationEnabled; }
        public double getDefaultCpuThreshold() { return defaultCpuThreshold; }
        public double getDefaultMemoryThreshold() { return defaultMemoryThreshold; }
        public double getDefaultResponseTimeThreshold() { return defaultResponseTimeThreshold; }
        public double getDefaultErrorRateThreshold() { return defaultErrorRateThreshold; }
        public long getTimestamp() { return timestamp; }
        
        public double getDegradationRate() {
            return totalRequests > 0 ? (double) totalDegradedRequests / totalRequests : 0.0;
        }
        
        public double getFallbackRate() {
            return totalRequests > 0 ? (double) totalFallbackRequests / totalRequests : 0.0;
        }
    }
}
